package com.zykj.thread.concurrent.lock.condition;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author zhoulj(周利军) [1217102780@qq.com]
 * @Module ID:   <(模块)类编号，可以引用系统设计中的类编号>
 * @Comments: <对此类的描述，可以引用系统设计中的描述>
 * @JDK version used:      <JDK1.8> 43
 * @since 2019/1/14-14:43
 */
//TODO 面试题：  子线程循环10次 主线程再循环5次，  总循环50次
public class ThreadSubFor {
    public static void main(String[] args) {
        final ThreadSub threadSub = new ThreadSub();
        new Thread((Runnable)() -> {
            for (int i = 0; i < 50; i++) {
                threadSub.sub(i);
            }
        }).start();


        for (int i = 0; i < 50; i++) {
            threadSub.main(i);

        }

    }

}

//TODO 总结：锁或线程同步控制  不是放在同步代码块中 而是放在资源内部的
class ThreadSub {
    volatile boolean subrun = true;
    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();
    public void main(int maini) {
//        if (subrun) {
        lock.lock();
        try {
            while(subrun) { //TODO 这里使用while 语义更好， 防止伪唤醒
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            for (int i = 0; i < 10; i++) {
                System.out.println("这是主线程：i="+maini+", j=" + (i+1));
            }
            subrun = true;

            //TODO 这里的this 对象 必须和synchronized 的锁对象必须是一致的
            condition.signal();
        }finally {
            lock.unlock();

        }

    }
    public void sub(int maini) {
//        if (!subrun) {
        lock.lock();
        try {
            while (!subrun) {
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            for (int j = 0; j < 5; j++) {
                System.out.println("这是子线程：i="+maini+", j=" + (j+1));
            }
            subrun = false;
            condition.signal();
        }finally {
            lock.unlock();
        }

    }
}